/********************************************************************************
*                                                                               *
* kWookaTypedResourceInfo.cpp -- some inner resources                           *
*                                                                               *
* Copyright (c) Fengren Technology(Guangzhou) Co.LTD. All rights reserved.      *
*                                                                               *
********************************************************************************/
#include "kWookaTypedResourceInfo.hpp"
#include "wx/wfstream.h"
#include "wx/txtstrm.h"
#include "wx/dir.h"

static wxString MySQLTemplate = wxT("[mysqld]\n"
	"default_authentication_plugin=mysql_native_password\n"
	"basedir=%s\n"
	"datadir=%s\n"
	"port=%s\n"
	"sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES\n"
	"character-set-server=utf8mb4\n"
	"performance_schema_max_table_instances=600\n"
	"table_definition_cache=400\n"
	"table_open_cache=256\n"
	"%s\n"
	"[mysql]\n"
	"default-character-set=utf8mb4\n"
	"[client]\n"
    "default-character-set=utf8mb4\n");

static wxString RedisTemplate = wxT("port %s\n"
	"bind 0.0.0.0\n"
	"tcp-backlog 511\n"
	"requirepass %s\n"
	"databases 16\n"
	"logfile stdout\n"
	"%s\n");

static wxString NginxTemplate = wxT("worker_processes  1;\n"
	"error_log %s/nginx/logs/error.log; \n"
	"pid  %s/nginx/logs/nginx.pid; \n"
	"events{ \n"
	"\tworker_connections  1024; \n"
	"}\n"
	"http{\n"
	"\tinclude    %s/conf/mime.types; \n"
	"\tdefault_type    application/octet-stream; \n"
	"\tlog_format  main  '$remote_addr - $remote_user [$time_local] \"$request\" '\n"
    "\t              '$status $body_bytes_sent \"$http_referer\" '\n"
    "\t              '\"$http_user_agent\" \"$http_x_forwarded_for\"'\n"
	"\taccess_log      %s/nginx/logs/access.log  main; \n"
	"\tsendfile        on; \n"
	"\tkeepalive_timeout  65; \n"
	"\n");

static wxString NginxServerTemplate = wxT("\t\tlisten      %s; \n"
	"\t\tserver_name  %s;\n"
	"\t\t%s\n");

static wxString MavenTemplate = wxT("\"%s\\bin\\mvn.cmd\" dependency:get dependency:copy -Dartifact=%s:%s:%s:jar -Dtransitive=false -DoutputDirectory=%s -DremoteRepositories=%s");


wxString FormatMavenCommand(kWookaProjectInfo* proj, kWookaAppItemInfo* appitem) {
	if (proj == NULL || appitem == NULL) {
		return wxT("ERROR");
	}
	if (proj != NULL && proj->mavenHome.IsEmpty()) {
		return wxT("ERROR");
	}
	if (appitem != NULL && appitem->appType != wxT("maven")) {
		return wxT("ERROR");
	}

	wxString defaultRepository = wxT("central::default::http://repo.maven.apache.org/maven2");
	wxString repository = wxT("");
	if (proj->mavenRepositories.Count() > 0) {
		for (size_t s = 0; s < proj->mavenRepositories.Count(); s++) {
			kWookaMavenRepoInfo& repo = proj->mavenRepositories[s];
			repository.Append(wxString::Format(wxT("%s::%s::%s"), repo.repoId, wxT("default"), repo.address));
			if (s < proj->mavenRepositories.Count() - 1) {
				repository.Append(wxT(","));
			}
		}
	}
	else {
		repository = defaultRepository;
	}

	return wxString::Format(MavenTemplate, proj->mavenHome, appitem->groupId, appitem->name, appitem->version, proj->workspace + wxT("\\") + appitem->name, repository);
}


wxString WriteRedisConfig(kWookaProjectInfo* proj, kWookaAppItemInfo* appitem) {
	if (proj == NULL || appitem == NULL) {
		return wxT("ERROR");
	}
	if (appitem != NULL && appitem->appType != wxT("redis")) {
		return wxT("ERROR");
	}

	//now, we will format and write down the config 
	wxString port = appitem->GetItemValue(wxT("RedisPort"));
	wxString authPasswd = appitem->GetItemValue(wxT("RedisAuthPassword"));
	wxString redisOptions = appitem->GetItemValue(wxT("RedisOptions"));

	wxString text = wxString::Format(RedisTemplate, port, authPasswd, redisOptions);

	wxString filename = wxString::Format(wxT("%s\\%s\\redis.conf"), proj->workspace, appitem->name);
	FileExists(filename);
	
	wxFileOutputStream fos(filename);
	wxTextOutputStream tos(fos);
	tos.WriteString(text);
	tos.Flush();
	fos.Close();

	return filename;
}

wxString WriteMySQLConfig(kWookaProjectInfo* proj, kWookaAppItemInfo* appitem) {
	if (proj == NULL || appitem == NULL) {
		return wxT("ERROR");
	}
	if (appitem != NULL && appitem->appType != wxT("mysql")) {
		return wxT("ERROR");
	}

	//now, we will format and write down the config 
	wxString port = appitem->GetItemValue(wxT("MySQLPort"));
	wxString authPasswd = appitem->GetItemValue(wxT("MySQLPort"));
	wxString mysqlOptions = appitem->GetItemValue(wxT("MySQLOptions"));
	wxString basedir = appitem->source; // The home of mysql install path
	wxString datadir = wxString::Format(wxT("%s\\%s\\data"), proj->workspace, appitem->name);

	if (appitem->ItemExist(wxT("MySQLDataDir"))) {
		datadir = appitem->GetItemValue(wxT("MySQLDataDir"));
	}
	basedir.Replace(wxT("\\"), wxT("/"), true);
	datadir.Replace(wxT("\\"), wxT("/"), true);

	wxString text = wxString::Format(MySQLTemplate, basedir, datadir, port, mysqlOptions);
	
	DirectoryExist(datadir, true);
	//MySQL should only have one config file for a project. 
	wxString filename = wxString::Format(wxT("%s\\%s\\mysql.ini"), proj->workspace, appitem->name);
	FileExists(filename);

	wxFileOutputStream fos(filename);
	wxTextOutputStream tos(fos);
	tos.WriteString(text);
	tos.Flush();
	fos.Close();
	return filename;
}

wxString WriteNginxServiceConfig(kWookaProjectInfo* proj, kWookaAppItemInfo* appitem) {
	if (proj == NULL || appitem == NULL) {
		return wxT("ERROR");
	}
	if (appitem != NULL && appitem->appType != wxT("nginx-service")) {
		return wxT("ERROR");
	}
	
	wxString options = appitem->GetItemValue(wxT("ServiceOptions"));
	
	
	//MySQL should only have one config file for a project. 
	wxString filename = wxString::Format(wxT("%s\\%s\\nginx-service.conf"), proj->workspace, appitem->name);
	FileExists(filename);

	wxFileOutputStream fos(filename);
	wxTextOutputStream tos(fos);
	tos.WriteString(appitem->source + " {\n");
	tos.WriteString(options);
	tos.WriteString(wxT("\n}\n"));
	tos.Flush();
	fos.Close();
	return filename;
}

static void WriteNginxOneConfig(kWookaProjectInfo* proj, kWookaAppItemInfo* appitem) {
	wxString serverName = appitem->name;
	wxString port = appitem->GetItemValue(wxT("ListenPort"));
	bool ipv6 = appitem->GetItemValue(wxT("IPv6Support")) == wxT("true");
	bool ssl = appitem->GetItemValue(wxT("SSLSupport")) == wxT("true");
	wxString options = appitem->GetItemValue(wxT("ServerOptions"));

	wxString filename = wxString::Format(wxT("%s\\%s\\nginx-server.conf"), proj->workspace, appitem->name);
	
	FileExists(filename);

	wxFileOutputStream fos(filename);
	wxTextOutputStream tos(fos);
	tos.WriteString(wxT("server {\n"));
	tos.WriteString(wxT("\tlisten ") + port + (ssl ? wxT(" ssl;\n") : wxT(";\n")));
	if (ipv6) {
		tos.WriteString(wxT("\tlisten  [::]:") + port + wxT("  ipv6only = on") + (ssl ? wxT(" ssl;\n") : wxT(";\n")));
	}
	tos.WriteString(wxT("\tserver_name ") + serverName + wxT(";\n"));
	options.Replace(wxT("\n"), wxT("\n\t"));
	tos.WriteString(options);
	tos.WriteString(wxT("\n}\n"));
	tos.Flush();
	fos.Close();
}

wxString WriteNginxConfig(kWookaProjectInfo* proj, kWookaAppItemInfo* appitem) {
	if (proj == NULL || appitem == NULL) {
		return wxT("ERROR");
	}
	if (appitem != NULL && appitem->appType != wxT("nginx-server")) {
		return wxT("ERROR");
	}

	wxString filename = wxString::Format(wxT("%s\\nginx\\nginx.conf"), proj->workspace, appitem->name);
	FileExists(filename);
	if (TRUE) {
		wxString ws = proj->workspace;
		wxString sc = appitem->source;
		ws.Replace(wxT("\\"), wxT("/"), true);
		sc.Replace(wxT("\\"), wxT("/"), true);

		wxString nginxText = wxString::Format(NginxTemplate, ws, ws, sc, ws);
		wxFileOutputStream fos(filename);
		wxTextOutputStream tos(fos);
		tos.WriteString(nginxText);
		//find all server
		for (size_t t = 0; t < proj->Applications.Count(); t++) {
			kWookaAppItemInfo& it = proj->Applications[t];
			if (it.appType == wxT("nginx-server")) {
				tos.WriteString(wxString::Format(wxT("\tinclude  %s/%s/nginx-server.conf;\n"), ws, it.name));
				WriteNginxOneConfig(proj, &it);
			}
		}
		tos.WriteString(wxT("\n}\n"));
		tos.Flush();
		fos.Close();
	}

	return filename;
}

bool FileExists(const wxString& fileName, bool mkdir) {
	bool exists = wxFile::Exists(fileName);
	if (exists) {
		return exists;
	}

	if (mkdir) {
		wxString path = wxPathOnly(fileName);
		DirectoryExist(path, mkdir);
	}
	return false;
}

bool DirectoryExist(const wxString& path, bool mkdir) {
	if (wxDir::Exists(path)) {
		return true;
	}
	else {
		if (mkdir) {
			return wxDir::Make(path);
		}
	}
	return false;
}

bool DirectoryRemove(const wxString& dir, bool recur) {
	wxArrayString files;
	wxDir::GetAllFiles(dir, &files);
	for (size_t st = 0; st < files.Count(); st++) {
		wxString fl = files[st];
		wxRemoveFile(fl);
	}
	wxDir::Remove(dir, recur ? 1 : 0);
	return true;
}
